<template>
  <div class="component-elx-imgbox">
    <el-dialog
      v-model="visible"
      :title="$t('pictureManager.picManager')"
      class="elx-imgbox-dialog"
      top="40px"
      width="900px"
      :append-to-body="visible"
      @close="onHandleDialogClose"
    >
      <div
        class="demo-tabs"
      >
        <div
          v-if="options.activeTab==='pick'"
          class="pick-block"
        >
          <div
            v-if="isLoading"
            class="elx-img-list-loading"
          >
            <div class="el-icon-loading" />
          </div>
          <el-form
            :inline="true"
            class="form"
            @submit.prevent
          >
            <el-form-item class="file-name-box">
              <el-input
                v-model="fileName"
                :placeholder="$t('pictureManager.picName')"
                clearable
              />
            </el-form-item>
            <el-form-item>
              <div
                class="default-btn primary-btn"
                @click="onSearchImg"
              >
                {{ $t('pictureManager.query') }}
              </div>
              <div
                v-if="options.enableUpload"
                class="default-btn primary-btn"
                style="margin-left: 10px"
                @click="onUploadPicClick"
              >
                {{ $t('pictureManager.uploadPic') }}
              </div>
            </el-form-item>
          </el-form>
          <div class="main">
            <div class="group-box">
              <div class="group">
                <div
                  :class="['group-item', groupId === 0 ? 'active' : '']"
                  @click="onClickGroup(0)"
                >
                  <span class="group-name">{{ $t('pictureManager.allPictures') }}</span>
                </div>
                <div
                  v-for="item in groupList"
                  :key="item.attachFileGroupId"
                  :class="['group-item', groupId === item.attachFileGroupId ? 'active' : '']"
                >
                  <span
                    class="group-name"
                    @click="onClickGroup(item.attachFileGroupId)"
                  >
                    {{ item.name }}
                  </span>
                </div>
              </div>
            </div>
            <div class="img-list">
              <div class="elx-main elx-img-list">
                <div
                  v-for="(img, itemIndex) in imgRes.records"
                  :key="itemIndex"
                  class="img-item"
                >
                  <div
                    class="thumb-wp"
                    @click="onClickListImage(img)"
                  >
                    <div class="image">
                      <img-show
                        :src="img.filePath"
                      />
                    </div>
                  </div>
                  <div
                    class="title"
                    @click="onClickListImage(img)"
                  >
                    {{ img.fileName }}
                  </div>
                  <span
                    v-if="img.selected"
                    class="selected"
                    @click="onClickListImage(img)"
                  >
                    <el-icon
                      size="18"
                      class="icon"
                    >
                      <Check />
                    </el-icon>
                  </span>
                </div>
                <el-empty
                  v-if="imgRes.records.length === 0"
                  :description="$t('user.noPic')"
                />
              </div>
              <el-pagination
                layout="total, prev, pager, next"
                :current-page="imgRes.current"
                :page-size="imgRes.size"
                :total="imgRes.total"
                @update:current-page="onPageChange"
              />
            </div>
          </div>
          <div class="elx-foot">
            <el-badge
              v-if="!type"
              :value="images.length"
              class="item"
            >
              <div
                class="default-btn"
                @click="visible = false"
              >
                {{ $t('resource.cancel') }}
              </div>
              <div
                :class="[images.length === 0 ? 'disabled-btn' : '', 'default-btn primary-btn']"
                style="margin-right: 3px"
                @click="onConfirm"
              >
                {{ $t('resource.confirm') }}
              </div>
            </el-badge>
            <div
              v-else
              :class="[images.length === 0 ? 'disabled-btn' : '', 'default-btn primary-btn']"
              @click="onConfirm"
            >
              {{ $t('resource.confirm') }}
            </div>
          </div>
        </div>

        <div
          v-if="options.enableUpload&&options.activeTab==='upload'"
          class="upload-block"
        >
          <div class="elx-main">
            <div class="upload-box">
              <div class="upload-title">
                {{ $t("resource.selectGroup") }}:
              </div>
              <div class="select-group-box">
                <div class="select-group-box-item">
                  {{ $t("resource.group") }}:
                </div>
                <el-select
                  v-model="selectGroup"
                  clearable
                  :placeholder="$t('resource.selectGroup')"
                  class="select-group-box-item"
                >
                  <el-option
                    v-for="item in groupList"
                    :key="item.attachFileGroupId"
                    :label="item.name"
                    :value="item.attachFileGroupId"
                  />
                </el-select>
                <el-button
                  style="margin-left: 10px"
                  link
                  type="primary"
                  @click="onCreateGroup()"
                >
                  {{ $t('resource.newGroup') }}
                </el-button>
              </div>
              <div class="upload-title">
                {{ $t("pictureManager.selectLocalPic") }}
              </div>
              <el-upload
                ref="uploadRef"
                class="upload-img-preview"
                list-type="picture-card"
                accept=".png,.jpg,.jpeg,.gif"
                action=""
                :http-request="handleFileChange"
                :headers="{Authorization: cookie.get('bbcAuthorization_vs'), locale:lang}"
                :multiple="true"
                :auto-upload="false"
                :limit="options.limit"
                :before-upload="beforeUpload"
                :on-change="onUploadChange"
                :on-exceed="onUploadExceedTip"
                :before-remove="onRemoveBefore"
                :on-remove="onHandleRemove"
                :class="{hide: hideUpload}"
              >
                <el-icon><Plus /></el-icon>
              </el-upload>

              <div class="upload-tip">
                {{ uploadTips() }}
              </div>

              <div class="elx-upload-foot">
                <div
                  class="default-btn"
                  @click="options.activeTab = 'pick'"
                >
                  {{ $t("shopFeature.edit.back") }}
                </div>
                <div
                  class="default-btn primary-btn"
                  @click="onUploadConfirm"
                >
                  {{ $t("pictureManager.confirmUpload") }}
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </el-dialog>
    <!-- /修改物流弹窗 -->
    <group-add-or-update
      v-if="groupVisible"
      ref="groupAddOrUpdateRef"
      @get-group-data="onGetGroupList"
    />
  </div>
</template>

<script setup>
import ImageCompressor from 'compressorjs'
import { ElMessage } from 'element-plus'
import { Check, Plus } from '@element-plus/icons-vue'
import http from '@/utils/http.js'
import cookie from 'vue-cookies'

const props = defineProps({
  maxSize: {
    default: null,
    type: Number
  },
  imgSizeLimit: {
    default: false,
    type: Boolean
  }
})
const emit = defineEmits(['refreshPic'])

const lang = ref(localStorage.getItem('bbcLang') || 'zh_CN')

const options = ref({
  multiple: true, // 是否支持选取多个图片
  limit: 20, // 最多可选择图片数量
  maxSize: 99999, // 最大尺寸（M）
  activeTab: 'pick',
  enableUpload: true, // 是否启用图片上传
  callback: null
})

watch(
  () => options.value.activeTab,
  (val) => {
    fileName.value = ''
    if (val === 'pick') {
      onLoadListImage(1)
    }
  }, { deep: true }
)

/**
 * 初始化
 * type 1：单图  2：多图
 */
const images = ref([]) // 已选图片
const fileIds = ref([]) // 已选图片的fileId
const type = ref()
const isLoading = ref(true)
const visible = ref(false)
const disabled = ref(false)
const hideUpload = ref(false)
let limit = null
const init = (pType, limitNum) => {
  options.value.activeTab = 'pick'
  visible.value = true
  isLoading.value = false
  images.value = []
  fileIds.value = []
  hideUpload.value = false
  type.value = pType
  if (pType === 1) {
    type.value = true
    disabled.value = true
  } else {
    type.value = false
    limit = limitNum
  }
  if (uploadRef.value) {
    uploadRef.value.uploadFiles = []
  }
  // 获取产品数据 - 第一页的数据
  onLoadListImage(1)
  onGetGroupList()
}
const onDelete = () => {
  images.value = [] // 已选图片
  fileIds.value = [] // 已选图片的fileId
  emit('refreshPic', null)
}
const onConfirm = () => {
  if (images.value.length === 0 || disabled.value) return
  if (type.value) {
    // 如果大于传过来的限制大小，则抛出异常
    const isSize = images.value[0].fileSize / (1024 * 1024) > options.value.maxSize
    if (isSize && options.value.maxSize < 1) {
      message($t('components.sizeCannotExceed') + options.value.maxSize * 1000 + 'K')
      return
    }
    if (isSize) {
      message($t('components.sizeCannotExceed') + options.value.maxSize + 'M')
      return
    }
    const img = new Image()
    img.src = checkFileUrl(images.value[0]?.filePath)
    img.onload = function () {
      if (props.imgSizeLimit && (img.width > 300 || img.height > 300)) {
        ElMessage.error($t('components.imageExc300Px'))
        return
      }
      emit('refreshPic', images.value[0].filePath)
      visible.value = false
    }
    img.onerror = function () {
      emit('refreshPic', images.value[0].filePath)
      visible.value = false
    }
  } else {
    const imgPaths = images.value.map(file => {
      return file.filePath
    }).join(',')
    emit('refreshPic', imgPaths)
    visible.value = false
  }
}
/**
 * 提交修改后的图片名称
 */
const selectGroup = ref('')
const imgRes = ref({
  current: 1,
  records: [],
  total: 0
})
/**
 * 获取分组列表
 */
const groupList = ref([]) // 分组列表
const groupVisible = ref(false)

const onGetGroupList = () => {
  groupVisible.value = false
  http({
    url: http.adornUrl('/admin/fileGroup/list'),
    method: 'get',
    params: {
      type: 1 // 1、图片 2、视频 3、文件
    }
  }).then(res => {
    groupList.value = res.data
  })
}
/**
 * 点击分组
 */
const groupId = ref('')

const onClickGroup = id => {
  groupId.value = id
  onLoadListImage()
}
/**
 * 点击图片上传
 */
const onUploadPicClick = () => {
  options.value.activeTab = 'upload'
  selectGroup.value = groupId.value || ''
  images.value = []
}

/**
 * 点击图片时选中或取消选中图片
 * @param img object
 */
const onClickListImage = img => {
  // 单选图片
  if (type.value) {
    onClearListSelected()
    images.value = []
    fileIds.value = []
    disabled.value = false
  } else {
    // 多选图片-如果已选中则取消选中
    const imgIndex = onSelectedImageIndex(img)
    if (imgIndex >= 0) {
      // 取消图片已选状态
      img.selected = false
      images.value.splice(imgIndex, 1)
      fileIds.value.splice(imgIndex, 1)
      return
    }
  }
  if (!type.value && images.value.length >= limit) {
    ElMessage($t('pictureManager.superiorLimit'))
    return false
  }

  images.value.push(JSON.parse(JSON.stringify(img)))
  fileIds.value.push(img.fileId)
  img.selected = true
}
/**
 * 清除所有已点击图片样式
 */
const onClearListSelected = () => {
  if (type.value) {
    const list = imgRes.value.records
    list.forEach(element => {
      element.selected = false
    })
  }
}
/**
 * 按图片名称搜索图片
 */
const onSearchImg = () => {
  onLoadListImage(1)
}
/**
 * 加载图片列表数据
 * @param page
 */
const fileName = ref('')

const onLoadListImage = (current) => {
  isLoading.value = true
  http({
    url: http.adornUrl('/admin/file/attachFilePage'),
    method: 'get',
    params: http.adornParams({
      current,
      size: 15,
      fileName: fileName.value || '',
      attachFileGroupId: groupId.value,
      type: 1
    })
  }).then(({ data }) => {
    imgRes.value = data
    imgRes.value.records?.forEach(img => {
      fileIds.value.indexOf(img.fileId) !== -1 ? img.selected = true : img.selected = false
    })
    isLoading.value = false
  })
}

/**
 * 图片已选则返回下标，未选则返回-1
 */
const onSelectedImageIndex = img => {
  for (let i = 0; i < images.value.length; i++) {
    const selectedImg = images.value[i]
    if (selectedImg.fileId === img.fileId) {
      return i
    }
  }
  return -1
}

/**
 * 分页页面变化时刷新数据
 * @param page
 */
const onPageChange = page => {
  onLoadListImage(page)
}
/**
 * 提交上传图片
 */
const uploadFlag = ref(0)
const notImg = ref(false)
const uploadSubmitFlag = ref(false)
const uploadRef = ref(null)
const onUploadConfirm = Debounce(() => {
  if (!uploadFileNum.value) {
    message($t('publics.imageNoNull'), false)
    return
  }
  uploadSubmitFlag.value = true
  const time = setTimeout(() => {
    uploadSubmitFlag.value = false
    clearTimeout(time)
  }, 1000)
  notImg.value = true
  uploadFlag.value = 0
  fileIds.value = []
  uploadRef.value?.submit()
})

// eslint-disable-next-line no-unused-vars
const onUploadChange = (uploadFile, UploadFiles) => {
  uploadFileNum.value = UploadFiles.length
  if (uploadFileNum.value >= options.value.limit) {
    hideUpload.value = true
  }
}
const uploadDisabled = ref(false)
const onRemoveBefore = () => {
  // 防止用户频繁点击导致删除过多
  return !uploadDisabled.value
}
// // 新建分组
const groupAddOrUpdateRef = ref(null)
const onCreateGroup = () => {
  groupVisible.value = true
  nextTick(() => {
    groupAddOrUpdateRef.value?.show(1)
  })
}

const uploadFileNum = ref(0)
const errShow = ref(false)
const picNum = ref(0)

const errMsg = () => {
  if (errShow.value && uploadFileNum.value === picNum.value) {
    picNum.value = 0
    message($t('pictureManager.onlyPictures'), true)
    notImg.value = false
  }
}
/**
 * 上传图片前检查合法性
 * @param file
 * @returns {boolean}
 */
const beforeUpload = async (file) => {
  picNum.value++
  const typeArray = file.type.split('/')
  errMsg()
  if (typeArray[0] !== 'image') {
    errShow.value = true
    errMsg()
    return Promise().reject()
  }
  if (uploadFileNum.value === picNum.value) {
    picNum.value = 0
  }
  const isSize = file.size / 1024 < 512
  if (!isSize) {
    // 0.5m~5m，从0.8开始循环。5m~10m，从0.6开始循环。10m以上就直接0.4。
    // 最低使用0.4
    let quality
    if (file.size / 1024 / 1024 < 5) {
      quality = 0.8
    } else if (file.size / 1024 / 1024 < 10) {
      quality = 0.6
    } else {
      quality = 0.4
    }
    try {
      let resultBlob
      let index = true
      while (index) {
        resultBlob = await ImageCompressorFn(file, quality)
        if (resultBlob.size / 1024 < 512 || quality <= 0.4) {
          index = false
        } else {
          quality = (quality * 10 - 2) / 10
        }
      }
      return new File([resultBlob], file.name, {
        type: file.type
      })
    } catch (error) {
      return false
    }
  }
  return true
}

const ImageCompressorFn = (file, quality) => {
  return new Promise((resolve, reject) => {
    // eslint-disable-next-line no-new
    new ImageCompressor(file, {
      quality, // 压缩大小
      convertSize: 512000,
      success (result) {
        resolve(result)
      },
      error (err) {
        reject(err)
      }
    })
  })
}

const onUploadNumberLimit = () => {
  if (!options.value.multiple) {
    return 1
  }
  return options.value.limit - images.value.length - uploadFileNum.value
}

const onUploadTypeTip = () => {
  return $t('pictureManager.onlySupported') + ' jpg/png/gif ' + $t('pictureManager.pic')
}

// const onUploadSizeTip = () => {
//   return $t('pictureManager.notExceed') + '2M'
// }

const uploadTips = () => {
  const tips = [onUploadTypeTip()]

  if (!options.value.multiple) {
    return tips.join('，')
  }

  if (images.value.length > 0) {
    tips.push($t('pictureManager.alreadyExist') + uploadFileNum.value + $t('pictureManager.unit'))
  }

  if (uploadFileNum.value > 0) {
    tips.push($t('pictureManager.soonUpload') + uploadFileNum.value + $t('pictureManager.unit'))
  }
  tips.push($t('pictureManager.remainder') + (options.value.limit - uploadFileNum.value) + $t('pictureManager.unit') + $t('pictureManager.upload'))

  return tips.join(',')
}

// eslint-disable-next-line no-unused-vars
const onHandleRemove = (file, fileList) => {
  uploadFileNum.value = fileList.length
  hideUpload.value = fileList.length >= options.value.limit
  hideUpload.value = false
  const time = setTimeout(() => {
    hideUpload.value = false
    clearTimeout(time)
  }, 1000)
  if (uploadSubmitFlag.value) {
    uploadDisabled.value = false
  } else {
    uploadDisabled.value = true
    const time1 = setTimeout(() => {
      uploadDisabled.value = false
      clearTimeout(time1)
    }, 1000)
  }
}

/**
 * 选择上传文件超过限制文件个数提示
 */
const onUploadExceedTip = () => {
  message($t('pictureManager.maxSelect') + onUploadNumberLimit() + $t('pictureManager.unit') + $t('pictureManager.upload'))
}
const message = (msg, isInfo) => {
  let type = 'error'
  if (isInfo) {
    type = 'info'
  }
  ElMessage({
    message: msg,
    type,
    duration: 1500
  })
}

/**
 * tab切换事件
 */
const onClickTab = (tab) => {
  fileName.value = ''
  if (tab.name === 'pick') {
    onLoadListImage(1)
  }
}
let resData = []
const handleFileChange = (e) => {
  const file = e.file
  http({
    url: http.adornUrl('/admin/file/getPreSignUrl'),
    method: 'get',
    params: http.adornParams({
      fileName: file.name,
      isImFile: false
    })
  }).then(async ({ data }) => {
    await uploadFile(data.preSignUrl, file).then(() => {
      resData.push({ fileId: data.fileId, attachFileGroupId: selectGroup.value, fileSize: file.size, type: 1 })
    }).catch((err) => {
      message($t('pictureManager.requestError'), true)
      throw err
    })
    if (uploadFileNum.value === resData.length) {
      http({
        url: http.adornUrl('/admin/file/uploadSuccess'),
        method: 'put',
        data: resData
      }).then(() => {
        resData = []
        hideUpload.value = false
        uploadRef.value.uploadFiles = []
        uploadRef.value.clearFiles()
        options.value.activeTab = 'pick'
        images.value = []
        fileIds.value = []
        selectGroup.value = ''
        onLoadListImage(1)
      })
    }
  })
}
onMounted(() => {
  onLoadListImage()
})
/**
 * 关闭回调
 */
const onHandleDialogClose = () => {
  fileName.value = ''
}
defineExpose({ init, onDelete, onClickTab })
</script>

<style lang="scss" scoped>
@use './index.scss';
</style>
